package com.neouton.crm.approval.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.PageDTO;
import com.neouton.common.entity.ActivitiVO;
import com.neouton.common.util.*;
import com.neouton.crm.approval.entity.ApprovalLogVO;
import com.neouton.crm.approval.entity.ApprovalVO;
import com.neouton.crm.approval.mapper.ApprovalMapper;
import com.neouton.crm.approval.service.IApprovalService;
import com.neouton.crm.cm.service.impl.CostMigrateServiceImpl;
import com.neouton.crm.dictionary.service.IDictionaryService;
import com.neouton.crm.entity.SysUserEntity;
import com.neouton.crm.op.service.impl.SalesOpportunityServiceImpl;
import com.neouton.crm.pm.mapper.SalesProjectManageMapper;
import com.neouton.crm.pm.service.impl.SalesProjectManageServiceImpl;
import com.neouton.crm.product.mapper.ProductInfoMapper;
import com.neouton.feginClient.FeginService;
import com.neouton.feginClient.WorkFlowFeginService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.sql.Timestamp;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;

@Service
public class ApprovalServiceImpl implements IApprovalService {

    @Resource
    private ApprovalMapper approvalMapper;

    @Resource
    private ProductInfoMapper productInfoMapper;

    @Resource
    private WorkFlowFeginService workFlowFeginService;

    @Resource
    private IDictionaryService dictionaryService;

    @Resource
    private SalesProjectManageMapper projectManageMapper;

    @Resource
    private FeginService feginService;

    @Resource
    @Lazy
    private CostMigrateServiceImpl costMigrateService;
    @Resource
    @Lazy
    private SalesOpportunityServiceImpl opportunityService;
    @Resource
    @Lazy
    private SalesProjectManageServiceImpl projectManageService;

    @Value("${webSit.web}")
    private String webSitUrl;

    /**
     * 分页查询待办任务
     * @param page
     * @param approval
     * @return
     */
    @Override
    public PageUtil<ApprovalVO> queryApprovalByPage(IPage<ApprovalVO> page, ApprovalVO approval) {
        //1.调取工作流
        ActivitiVO activitiVO = new ActivitiVO();
        activitiVO.setAuthorization(AuthUtils.getUserAccount());
        ResponseAPI<List<ActivitiVO>> workFlowVoResponseAPI = workFlowFeginService.getTasksByAuthorization(activitiVO);
        List<ActivitiVO> activitiVOS = workFlowVoResponseAPI.getResult();
        if( activitiVOS == null || activitiVOS.size() == 0 ){
            return new PageUtil(new PageDTO());
        }else{
            return new PageUtil(approvalMapper.queryApprovalByPage(page,approval,activitiVOS));
        }
    }

    @Override
    public List<ApprovalVO> queryApprovalByPage(ApprovalVO approval) {
        //1.调取工作流
        ActivitiVO activitiVO = new ActivitiVO();
        activitiVO.setAuthorization(AuthUtils.getUserAccount());
        ResponseAPI<List<ActivitiVO>> workFlowVoResponseAPI = workFlowFeginService.getTasksByAuthorization(activitiVO);
        List<ActivitiVO> activitiVOS = workFlowVoResponseAPI.getResult();
        if( activitiVOS == null || activitiVOS.isEmpty() ){
            return null;
        }else{
            return approvalMapper.queryApprovalByPage(approval,activitiVOS);
        }
    }

    /**
     * 更具ID查询审批主表
     * @param approvalId
     * @return
     */
    public ApprovalVO queryApprovalByAppID(Integer approvalId){
        return approvalMapper.queryApprovalByAppID(approvalId);
    }

    /**
     * 查询审批日志
     * @param approvalId
     * @return
     */
    public List<ApprovalLogVO> queryApprovalLogByAppID(Integer approvalId){
        return approvalMapper.queryApprovalLogByAppID(approvalId);
    }

    /**
     * 发我审批，生成审批主表信息
     * @param approval 主表信息
     * @return
     */
    public Boolean initiateApproval(ApprovalVO approval){
        return approvalMapper.insertApproval(approval);
    }

    /**
     * 审批通过 多字段判断，可根据工作流ID，审批表主键进行操作
     * @param businessId 工作流ID
     * @param approvalId 与待办通知数据保持一致，统一为auth数据字典配置字段
     * @return
     */
    public Boolean approved(Integer businessId,Integer approvalId){
        return approvalMapper.approved(businessId,approvalId);
    }

    /**
     * 审批驳回 多字段判断，可根据工作流ID，审批表主键进行操作
     * @param businessId 工作流ID
     * @param approvalId 与待办通知数据保持一致，统一为auth数据字典配置字段
     * @return
     */
    public Boolean approvalRejection(Integer businessId,Integer approvalId){
        return approvalMapper.approvalRejection(businessId,approvalId);
    }

    /**
     *
     * @param approvalId 审批主表ID
     * @param operationType 操作类型
     * @param operationDesc 操作描述
     * @param opinion 审批意见
     * @return
     */
    public Boolean insertApprovalLog(Integer approvalId,String operationType,String operationDesc,String opinion){
        ApprovalLogVO approvalLog = new ApprovalLogVO();
        approvalLog.setApprovalId(approvalId);
        approvalLog.setOperationType(operationType);
        approvalLog.setOperationDesc(operationDesc);
        approvalLog.setOpinion(opinion);
        return approvalMapper.insertApprovalLog(approvalLog);
    }

    /**
     * 生成审批主表，同时生成日志表
     * @param businessId 工作流ID
     * @param approvalType 审批类型，与auth数据字典配置一致
     * @param askReason 申请原因
     * @param operationDesc 操作描述
     * @return 审批主表主键
     */
    public ApprovalVO initApprovalAndLog(Integer businessId,Integer approvalType,String askReason,
                                      String operationDesc,Integer nextApprover,String remark){
        //生成审批主表信息
        ApprovalVO approval = new ApprovalVO();
        approval.setBusinessId(businessId);
        approval.setApprovalType(approvalType);
        approval.setAskReason(askReason);
        approval.setNextApprover(nextApprover);
        approval.setRemark(remark);
        //获取当日最大单号
        approval.setApprovalCode(this.queryMaxApprovalcodeByDate());
        this.initiateApproval(approval);
        //生成日志表信息
        this.insertApprovalLog(approval.getApprovalId(),"提交",operationDesc,approval.getAskReason());
        return approval;
    }

    /**
     * 查询审批记录，更具审批类型
     * @param page 分页
     * @param approval 审批实体类
     * @return
     */
    @Override
    public PageUtil<ApprovalVO> queryApprovalRecordByType(IPage<ApprovalVO> page, ApprovalVO approval, String token){
        List<SysUserEntity> userList = this.queryUserList(AuthUtils.getUserId(),"approvalRecord", token);
        //5.过滤字段，选取各审批环节需查询的人员集合，限定范围，避免查询越界
        return new PageUtil(approvalMapper.queryApprovalRecordByType(page,approval,userList));
    }
    @Override
    public List<ApprovalVO> queryApprovalRecordByType(ApprovalVO approval, String token){
        List<SysUserEntity> userList = this.queryUserList(AuthUtils.getUserId(),"approvalRecord", token);
        //5.过滤字段，选取各审批环节需查询的人员集合，限定范围，避免查询越界
        return approvalMapper.queryApprovalRecordByType(approval,userList);
    }


    /**
     * 已办审批查询
     * @param pageNum
     * @param pageSize
     * @param approval
     * @return
     */
    public PageUtil<ApprovalVO> queryApprovalDoneRecordByType(Integer pageNum, Integer  pageSize, ApprovalVO approval){
        List<ApprovalVO> result =approvalMapper.queryApprovalDoneRecordByType(approval);
        Integer total = result.size();
        Integer size = pageNum * pageSize;
        Integer num = (pageNum - 1) * pageSize;
        List<ApprovalVO> pageList = result.subList(num > total ? 0 : num, total < size ? total : size);
        PageUtil pageUtil = new PageUtil(total.longValue(), pageSize.longValue(), pageNum.longValue(), pageList);
        return pageUtil;
    }
    public List<ApprovalVO> queryApprovalDoneRecordByType(ApprovalVO approval){
        return approvalMapper.queryApprovalDoneRecordByType(approval);
    }


    /**
     * 确定每项申请记录当前登录人的查询范围
     */
    private List<Integer> querySelectUserScope(String menuCode,SysUserEntity loginUser
            ,List<SysUserEntity> allUsers,List<SysUserEntity> leaderUsers){
        List<SysUserEntity> users = dictionaryService.queryMenuUserIdsByCode(menuCode);
        if (loginUser.getUserId().intValue() == users.get(0).getUserId().intValue()){
            return allUsers.stream().map(o -> o.getUserId()).collect(Collectors.toList());
        }else {
            if (loginUser.getIsLeader() == 1){
                return leaderUsers.stream().map(o -> o.getUserId()).collect(Collectors.toList());
            }else {
                List<SysUserEntity> loginsUserList = new ArrayList<>();
                loginsUserList.add(loginUser);
                return loginsUserList.stream().map(o -> o.getUserId()).collect(Collectors.toList());
            }
        }
    }

    public String queryMaxApprovalcodeByDate(){
        Integer num = approvalMapper.queryMaxApprovalcodeByDate();
        String numStr;
        if(num<10){
            numStr = "00" + num;
        }else if(num>=10 && num<99){
            numStr = "0" + num;
        }else {
            numStr = "" + num;
        }
        String strNum = "CRM-A-" + DateUtils.getDateNum() + numStr;
        return strNum;
    }

    /**
     * 更新下一处理人
     * @param userId 下一处理人ID
     * @param approvalId 审批ID
     * @return
     */
    public Boolean updateNextApproverByApprovalId(Integer userId,Integer approvalId){
       return approvalMapper.updateNextApproverByApprovalId(userId,approvalId);
    }

    /**
     * 撤回工作流
     * @param approval 审批实例
     * @return
     */
    public Boolean deleteInstance(ApprovalVO approval,String token){
        ActivitiVO activitiVO = new ActivitiVO();
        activitiVO.setAuthorization(AuthUtils.getUserAccount());
        activitiVO.setBusinessId(approval.getBusinessId());
        workFlowFeginService.deleteInstance(activitiVO);
        //1.生成日志
        this.insertApprovalLog(approval.getApprovalId(),"撤回",
                "",approval.getOpinion());
        //2.修改状态为撤回
        approvalMapper.approvalWithdrawal(approval.getBusinessId(),approval.getApprovalId());
        //同时更改撤回信息
        this.updateWithdrawalInfo(approval,token);
        //3.修改当前处理人为自己  清空处理人
        this.updateNextApproverByApprovalId(-1,approval.getApprovalId());
        //4.销毁待办审批
        NoticUtils.pushNotic(approval.getApprovalId(), new Timestamp(System.currentTimeMillis()),
                AuthUtils.getUserId(),1,approval.getApprovalType(),0,token);
        if(!approval.getCreator().equals(AuthUtils.getUserId())){
            //1.获取个人信息
            SysUserEntity user = feginService.searchUserInfoByIds(approval.getCreator(), token).getResult();
            //如果不是自己撤回的，发邮件
            String titel = "【系统通知】单据撤回通知";
            String msg =  "<div><p >" + "尊敬的" + user.getLoginName() + "：</p></div>" +
                    "<div><p style='text-indent: 2em'>您好，您有一张已通过的申请单被管理员撤回：</p></div>"+
                    "<div><p style='text-indent: 2em'>事项编号："+approval.getApprovalCode()+"</p></div>"+
                    "<div><p style='text-indent: 2em'>事项类型："+(getApprovalTypeByCode(approval.getApprovalType()))+"</p></div>"+
                    "<div><p style='text-indent: 2em'>撤回人："+AuthUtils.getUserName()+" / "+AuthUtils.getUserAccount()+"</p></div>"+
                    "<div><p style='text-indent: 2em'>系统查看路径：客户关系管理系统 - 待办事项 - 申请记录 " +
                    "<a href='"+webSitUrl+"/?m=crm&p=crmtodoItems&me=productApprovalRecord'>进入</a></p></div>"+
                    "<div><p style='text-indent: 2em'>谢谢！</p></div>"+
                    "<div><p style='text-indent: 2em'>说明：该邮件为系统自动发送，请勿回复。</p></div>";
            CompletableFuture.runAsync(() -> EmailUtils.sentMailByAddressee(user.getEmail(),null,titel,msg,token));
        }
        if(approval.getApprovalType().equals(4)){
            //产品撤回，产品状态修改为禁用
            productInfoMapper.updateProductStatusByApprovalId(0,approval.getApprovalId());
        }
        if(approval.getApprovalType().equals(50)){
            //项目变更撤回，需要将项目表变更状态改为已撤回
            projectManageMapper.updateProjectStatusByApproveId(approval.getApprovalId(),3);
            // 变更按钮可编辑，清空可清空
            projectManageMapper.deleteUpdateInfoAfterRevoke(approval.getApprovalId());
        }
        return true;
    }

    /**
     * 获取审批日志
     * @param approvalId
     * @return
     */
    public List<Map<String,String>> queryApprovalLog(Integer approvalId){
        return approvalMapper.queryApprovalLog(approvalId);
    }

    @Override
    public List<Map<String, String>> queryApprovalLogList(List<Integer> approvalIdList) {
        return null;
    }

    /**
     * 提交撤回申请
     * @param approval
     * @return
     */
    public Boolean saveWithdraw(ApprovalVO approval,String token){
        //获取审批人
        List<SysUserEntity> users = dictionaryService.queryMenuUserIdsByCode("commercialSpecialist");
        //获取人员信息
        SysUserEntity user = users.get(0);
        //1.发起工作流
        Integer businessId = this.startWithdrawApproval(user);
        //2.保存实体
        //生成审批主表信息，日志信息
        ApprovalVO approvalRes = this.initApprovalAndLog(businessId, 30, approval.getAskReason(),
                "",user.getUserId(),approval.getApprovalId().toString());
        //获取原事项数据
        ApprovalVO approvalVO = this.queryApprovalByAppID(approval.getApprovalId());
        //原记录添加撤回申请日志
        this.insertApprovalLog(approvalVO.getApprovalId(),"提交撤回申请",approvalRes.getApprovalCode(),approval.getAskReason());
        //3.邮件、通知
//        String titel = "【系统通知】单据撤回 - 流程单审批通知";
//        String msg =  "<div><p >" + "尊敬的" + user.getLoginName() + "：</p></div>" +
//                "<div><p style='text-indent: 2em'>您好，您有一张新的单据撤回审批需要处理：</p></div>"+
//                "<div><p style='text-indent: 2em'>申请人："+AuthUtils.getUserName() +" / "+ AuthUtils.getUserAccount()+"</p></div>"+
//                "<div><p style='text-indent: 2em'>申请原因："+(StringUtils.isEmpty(approval.getAskReason()) ? "无":approval.getAskReason())+"</p></div>"+
//                "<div><p style='text-indent: 2em'>申请时间："+DateUtils.getCurrentTime()+"</p></div>"+
//                "<div><p style='text-indent: 2em'>事项编号："+approvalRes.getApprovalCode()+"</p></div>"+
//                "<div><p style='text-indent: 2em'>撤回事项编号："+approvalVO.getApprovalCode()+"</p></div>"+
//                "<div><p style='text-indent: 2em'>撤回事项类型："+(getApprovalTypeByCode(approvalVO.getApprovalType()))+"</p></div>"+
//                "<div><p style='text-indent: 2em'>系统审批路径：客户关系管理系统 - 待办事项 - 待办审批 " +
//                "<a href='"+webSitUrl+"/?m=crm&p=crmtodoItems&me=todoApprovalPath'>进入</a></p></div>"+
//                "<div><p style='text-indent: 2em'>谢谢！</p></div>"+
//                "<div><p style='text-indent: 2em'>说明：该邮件为系统自动发送，请勿回复。</p></div>";
//        CompletableFuture.runAsync(() -> EmailUtils.sentMailByAddressee(user.getEmail(),null,titel,msg,token));
        //调用通知接口
        Integer userId = AuthUtils.getUserId();
        CompletableFuture.runAsync(() -> NoticUtils.pushNotic(approvalRes.getApprovalId(),
                new Timestamp(System.currentTimeMillis()),userId, 0,30,user.getUserId(),token));
        //修改原单据状态为撤回审批中
        approvalMapper.startApprovalWithdrawal(null,approval.getApprovalId());
        if(approval.getApprovalType().equals(4)){
            //产品撤回，产品状态修改为禁用
            productInfoMapper.updateProductStatusByApprovalId(0,approval.getApprovalId());
        }
        return true;
    }

    /**
     * 审批通过
     * @param approval
     * @return
     */
    @Transactional
    public Boolean approveWithdraw(ApprovalVO approval,String token){
        ActivitiVO activitiVO = new ActivitiVO();
        activitiVO.setAuthorization(AuthUtils.getUserAccount());
        activitiVO.setBusinessId(approval.getBusinessId());
        workFlowFeginService.approvalProcessByBusinessId(activitiVO);
        //获取原事项数据
        ApprovalVO approvalVO = this.queryApprovalByAppID(Integer.parseInt(approval.getRemark()));
        //发送邮件
        ResponseAPI<SysUserEntity> res = feginService.searchUserInfoByIds(approval.getCreator(),token);
        SysUserEntity user = res.getResult();
        //发送邮件
        String titel = "【系统通知】单据撤回 - 流程单审批通过通知";
        String msg;
        msg =  "<div><p>" + "尊敬的" + user.getLoginName() + "：</p></div>" +
                "<div><p style='text-indent: 2em'>您好，您申请的单据撤回已通过：</p></div>"+
                "<div><p style='text-indent: 2em'>事项编号："+approval.getApprovalCode()+"</p></div>"+
                "<div><p style='text-indent: 2em'>审批人："+AuthUtils.getUserName() +" / "+AuthUtils.getUserAccount()+"</p></div>"+
                "<div><p style='text-indent: 2em'>审批意见："+(StringUtils.isEmpty(approval.getOpinion()) ? "无":approval.getOpinion())+"</p></div>"+
                "<div><p style='text-indent: 2em'>审批时间："+DateUtils.getCurrentTime()+"</p></div>"+
                "<div><p style='text-indent: 2em'>撤回事项编号："+approvalVO.getApprovalCode()+
                "<div><p style='text-indent: 2em'>撤回事项类型："+(getApprovalTypeByCode(approvalVO.getApprovalType()))+"</p></div>"+"</p></div>"+
                "<div><p style='text-indent: 2em'>系统查看路径：客户关系管理系统 - 待办事项 - 申请记录 " +
                "<a href='"+webSitUrl+"/?m=crm&p=crmtodoItems&me=productApprovalRecord'>进入</a></p></div>"+
                "<div><p style='text-indent: 2em'>谢谢！</p></div>"+
                "<div><p style='text-indent: 2em'>说明：该邮件为系统自动发送，请勿回复。</p></div>";
        CompletableFuture.runAsync(() -> EmailUtils.sentMailByAddressee(user.getEmail(),null,titel,msg,token));
        //调用通知接口
        CompletableFuture.runAsync(() -> NoticUtils.pushNotic(approval.getApprovalId(),approval.getCreateDataTime(),
                approval.getCreator(),1,30,0,token));
        this.insertApprovalLog(approval.getApprovalId(),"通过",
                "",approval.getOpinion());
        //原记录添加撤回去通过日志
        this.insertApprovalLog(Integer.parseInt(approval.getRemark()),"通过",
                "撤回申请",approval.getOpinion());
        //修改原单据数据
        approvalMapper.approvalWithdrawal(null,Integer.parseInt(approval.getRemark()));
        //同时更改撤回信息
        this.approvalWithdrawalInfo(approval,token);
        return this.approved(null,approval.getApprovalId());
    }

    /**
     * 审批驳回
     * @param approval
     * @return
     */
    @Transactional
    public Boolean rejectionWithdraw(ApprovalVO approval, String token){
        ActivitiVO activitiVO = new ActivitiVO();
        activitiVO.setAuthorization(AuthUtils.getUserAccount());
        activitiVO.setBusinessId(approval.getBusinessId());
        workFlowFeginService.approvalProcessByBusinessId(activitiVO);

        ResponseAPI<SysUserEntity> res = feginService.searchUserInfoByIds(approval.getCreator(),token);
        SysUserEntity user = res.getResult();
        //获取原事项数据
        ApprovalVO approvalVO = this.queryApprovalByAppID(Integer.parseInt(approval.getRemark()));
        //发送邮件
        String titel = "【系统通知】单据撤回 - 流程单审批驳回通知";
        String msg;
        msg =  "<div><p>" + "尊敬的" + user.getLoginName() + "：</p></div>" +
                "<div><p style='text-indent: 2em'>您好，您申请的单据撤回已被驳回：</p></div>"+
                "<div><p style='text-indent: 2em'>事项编号："+approval.getApprovalCode()+"</p></div>"+
                "<div><p style='text-indent: 2em'>审批人："+AuthUtils.getUserName() +" / "+AuthUtils.getUserAccount() +"</p></div>"+
                "<div><p style='text-indent: 2em'>审批意见："+(StringUtils.isEmpty(approval.getOpinion()) ? "无":approval.getOpinion())+"</p></div>"+
                "<div><p style='text-indent: 2em'>审批时间："+DateUtils.getCurrentTime()+"</p></div>"+
                "<div><p style='text-indent: 2em'>撤回事项编号："+approvalVO.getApprovalCode()+"</p></div>"+
                "<div><p style='text-indent: 2em'>撤回事项类型："+(getApprovalTypeByCode(approvalVO.getApprovalType()))+"</p></div>"+
                "<div><p style='text-indent: 2em'>系统查看路径：客户关系管理系统 - 待办事项 - 申请记录 " +
                "<a href='"+webSitUrl+"/?m=crm&p=crmtodoItems&me=productApprovalRecord'>进入</a></p></div>"+
                "<div><p style='text-indent: 2em'>谢谢！</p></div>"+
                "<div><p style='text-indent: 2em'>说明：该邮件为系统自动发送，请勿回复。</p></div>";
        CompletableFuture.runAsync(() -> EmailUtils.sentMailByAddressee(user.getEmail(),null,titel,msg,token));
        //调用通知接口
        CompletableFuture.runAsync(() -> NoticUtils.pushNotic(approval.getApprovalId(),
                approval.getCreateDataTime(), approval.getCreator(), 1,30,0,token));
        this.insertApprovalLog(approval.getApprovalId(),"驳回",
                "",approval.getOpinion());
        //原记录添加撤回去驳回日志
        this.insertApprovalLog(Integer.parseInt(approval.getRemark()),"驳回","撤回申请",approval.getOpinion());
        //修改原单据状态为撤回审批中之前状态
        approvalMapper.rejectionWithdrawal(null,Integer.parseInt(approval.getRemark()));
        if(approval.getApprovalType().equals(4)){
            //产品撤回，产品状态修改为启用
            productInfoMapper.updateProductStatusByApprovalId(1,approval.getApprovalId());
        }
        return this.approvalRejection(null,approval.getApprovalId());
    }

    /**
     * 开启审批流程
     * @return
     */
    private Integer startWithdrawApproval(SysUserEntity user){
        ActivitiVO activitiVO = new ActivitiVO();
        activitiVO.setAuthorization(AuthUtils.getUserAccount());
        activitiVO.setProcessName("申请撤回审批流程");
        activitiVO.setProcessCode("withdraw_approval");
        activitiVO.setVersion("1");
        activitiVO.setNextNodeParams("user");
        activitiVO.setNextNodeAssignee(user.getAccount());
        ResponseAPI<ActivitiVO> responseAPI = workFlowFeginService.startProcessByDesignCodeVersionCustomParams(activitiVO);
        return responseAPI.getResult().getBusinessId();
    }

    /**
     * 查看一个字符串是否可以转换为数字
     * @param str 字符串
     * @return true 可以; false 不可以
     */
    public static boolean isStr2Num(String str) {
        try {
            Integer.parseInt(str);
            return true;
        } catch (NumberFormatException e) {
            return false;
        }
    }

    /**
     * 直接撤回
     * @param approval
     * @param token
     */
    public void updateWithdrawalInfo(ApprovalVO approval,String token) {
        Integer type = approval.getApprovalType();
        if (type == Constants.OPPORTUNITY_AUDIT_TASK_TYPE) {
            opportunityService.opportunityWithdrawal(approval, token);
        }
        if (type == Constants.PROJECT_TASK_TYPE) {
            projectManageService.projectApprovalWithdrawal(approval, token);
        }
        if (type == Constants.COSTRECORD_TASK_TYPE) {
            costMigrateService.costRecordWithdrawal(approval, token);
        }
        if (type == Constants.COSTMIGRATE_TASK_TYPE) {
            costMigrateService.costMigrateWithdrawal(approval, token);
        }
        if (type == Constants.PROJECT_TASK_TYPE_ONE) {
            projectManageService.projectApprovalOneWithdrawal(approval, token);
        }
    }

    /**
     * 通过后撤回
     * @param approvalVO
     * @param token
     */
    public void approvalWithdrawalInfo(ApprovalVO approvalVO,String token) {
        if (isStr2Num(approvalVO.getRemark())) {
            ApprovalVO approval = this.queryApprovalByAppID(Integer.valueOf(approvalVO.getRemark()));
            Integer type = approval.getApprovalType();
            if (type == Constants.OPPORTUNITY_AUDIT_TASK_TYPE) {
                opportunityService.opportunityWithdrawal(approval, token);
            }
            if (type == Constants.PROJECT_TASK_TYPE) {
                projectManageService.projectApprovalWithdrawal(approval, token);
            }
            if (type == Constants.COSTRECORD_TASK_TYPE) {
                costMigrateService.costRecordWithdrawal(approval, token);
            }
            if (type == Constants.COSTMIGRATE_TASK_TYPE) {
                costMigrateService.costMigrateWithdrawal(approval, token);
            }
            if (type == Constants.PROJECT_TASK_TYPE_ONE) {
                projectManageService.projectApprovalOneWithdrawal(approval, token);
            }
        }
    }

    private String getApprovalTypeByCode(Integer ApprovalTypeCode){
        List<String> param = new ArrayList<>();
        param.add("todoType");
        JSONObject jsonObject = feginService.queryDictionaryLookupInfo("crm", param);
        LinkedHashMap linkedHashMap = (LinkedHashMap) jsonObject.get("result");
        List<Map> todoTypes = (List) linkedHashMap.get("todoType");

        for (Map<String,String> todoType:todoTypes){
            if (todoType.get("itemCode").equals(ApprovalTypeCode+"")){
                return todoType.get("itemName");
            }
        }
        return "";
    }

    public List<SysUserEntity> queryUserList(Integer userId,String authCode, String token) {
        List<SysUserEntity> userList = new ArrayList<>();
        List<SysUserEntity> authUserIList = dictionaryService.queryAuthUserIdsByCode(authCode);
        boolean result = false;
        for (SysUserEntity user:authUserIList) {
            if (Objects.equals(user.getUserId(), userId)) {
                result = true;
            }
        }
        if (result) {
            userList = feginService.getUserIgnoreFlag(token).getResult();
        } else {
            SysUserEntity user = feginService.searchUserInfoByIds(userId,token).getResult();
            if (user.getIsLeader() == 1) {
                userList = feginService.recursiveQueryAllUserByLeaderId(userId, token).getResult();
            }
            userList.add(user);
        }
        return userList;
    }

    /**
     * 分页查询待办任务
     * @param page
     * @param approval
     * @return
     */
    @Override
    public PageUtil<ApprovalVO> queryWithdrawalApprovalByPage(IPage<ApprovalVO> page, ApprovalVO approval) {
        //1.调取工作流
        ActivitiVO activitiVO = new ActivitiVO();
        activitiVO.setAuthorization(AuthUtils.getUserAccount());
        ResponseAPI<List<ActivitiVO>> workFlowVoResponseAPI = workFlowFeginService.getTasksByAuthorization(activitiVO);
        List<ActivitiVO> activitiVOS = workFlowVoResponseAPI.getResult();
        if( activitiVOS == null || activitiVOS.size() == 0 ){
            return new PageUtil(new PageDTO());
        }else{
            return new PageUtil(approvalMapper.queryWithdrawalApprovalByPage(page,approval,activitiVOS));
        }
    }

    /**
     * 已办审批查询
     * @param pageNum
     * @param pageSize
     * @param entity
     * @return
     */
    public PageUtil<ApprovalVO> queryWithdrawalApprovalDoneRecordByType(Integer pageNum, Integer  pageSize, ApprovalVO approval){
        List<ApprovalVO> result =approvalMapper.queryWithdrawalApprovalDoneRecordByType(approval);
        Integer total = result.size();
        Integer size = pageNum * pageSize;
        Integer num = (pageNum - 1) * pageSize;
        List<ApprovalVO> pageList = result.subList(num > total ? 0 : num, total < size ? total : size);
        PageUtil pageUtil = new PageUtil(total.longValue(), pageSize.longValue(), pageNum.longValue(), pageList);
        return pageUtil;
    }

    /**
     * 查询审批记录，更具审批类型
     * @param page 分页
     * @param approval 审批实体类
     * @return
     */
    @Override
    public PageUtil<ApprovalVO> queryWithdrawalApprovalRecordByType(IPage<ApprovalVO> page, ApprovalVO approval, String token){
        List<SysUserEntity> userList = this.queryUserList(AuthUtils.getUserId(),"approvalRecord", token);
        //5.过滤字段，选取各审批环节需查询的人员集合，限定范围，避免查询越界
        return new PageUtil(approvalMapper.queryWithdrawalApprovalRecordByType(page,approval,userList));
    }


    @Override
    public List<String> queryApprovalStepsByApprovalCode(String approvalCode){
        return approvalMapper.queryApprovalStepsByApprovalCode(approvalCode);
    }
}
